// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#include <string>
#include <pollux/type/type.h>

namespace kumo::pollux {
    TypePtr typeFromString(
        const std::string &type,
        bool failIfNotRegistered = true) {
        auto upper = type;
        std::transform(upper.begin(), upper.end(), upper.begin(), ::toupper);
        if (upper == "INT") {
            upper = "INTEGER";
        } else if (upper == "DOUBLE PRECISION") {
            upper = "DOUBLE";
        }
        auto inferredType = getType(upper, {});
        if (failIfNotRegistered == true && inferredType == nullptr) {
            POLLUX_UNSUPPORTED("Failed to parse type [{}]. Type not registered.", type);
        }
        return inferredType;
    }

    TypePtr customTypeWithChildren(
        const std::string &name,
        const std::vector<TypePtr> &children) {
        std::vector<TypeParameter> params;
        params.reserve(children.size());
        for (auto &child: children) {
            params.emplace_back(child);
        }
        auto type = getType(name, params);
        POLLUX_CHECK_NOT_NULL(
            type, "Failed to parse custom type with children [{}]", name);
        return type;
    }

    std::pair<std::string, std::shared_ptr<const Type> > inferTypeWithSpaces(
        std::vector<std::string> &words,
        bool cannotHaveFieldName = false) {
        POLLUX_CHECK_GE(words.size(), 2);
        const auto &fieldName = words[0];
        const auto allWords = melon::join(" ", words);
        // Fail if cannotHaveFieldName = true.
        auto type = typeFromString(allWords, cannotHaveFieldName);
        if (type) {
            return std::make_pair("", type);
        }
        return std::make_pair(
            fieldName, typeFromString(allWords.substr(fieldName.size() + 1)));
    }
} // namespace kumo::pollux
